#ifndef CORE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define CORE

#if defined(__GNUC__) && __GNUC__ >= 4
# define API __attribute__ ((visibility("default")))
#else
# define API
#endif

#define SUCCESS 	0
#define FAILURE		-1

/* 定义数据类型 */
#define IS_NULL		0
#define IS_LONG		1
#define IS_DOUBLE	2
#define IS_BOOL		3
#define IS_ARRAY	4
#define IS_OBJECT	5
#define IS_STRING	6

typedef union _zval_value{
	//长整形
	long lval;

	double dval;

	//字符串
	struct{
		char* val;
		int len;
	} str;

	//等待实现Zend内核中的Hash表
	//HashTable ht;
	
	//obj对象
	//zvalObj obj;
}zval_value;

typedef struct _struct_zval{
	zval_value value;

	//定义变量类型
	char type;
} zval;

#define MAKE_STD_ZVAL(z) (z) = (zval *)malloc(sizeof(zval))

#define Z_LVAL(zval)			(zval).value.lval
#define Z_BVAL(zval)			((zend_bool)(zval).value.lval)
#define Z_DVAL(zval)			(zval).value.dval
#define Z_STRVAL(zval)			(zval).value.str.val
#define Z_STRLEN(zval)			(zval).value.str.len

#define Z_LVAL_P(zval_p)		Z_LVAL(*zval_p)
#define Z_BVAL_P(zval_p)		Z_BVAL(*zval_p)
#define Z_DVAL_P(zval_p)		Z_DVAL(*zval_p)
#define Z_STRVAL_P(zval_p)		Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p)		Z_STRLEN(*zval_p)

#define Z_LVAL_PP(zval_pp)		Z_LVAL(**zval_pp)
#define Z_BVAL_PP(zval_pp)		Z_BVAL(**zval_pp)
#define Z_DVAL_PP(zval_pp)		Z_DVAL(**zval_pp)
#define Z_STRVAL_PP(zval_pp)	Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp)	Z_STRLEN(**zval_pp)

#define Z_TYPE(z)				(z).type
#define Z_TYPE_P(z)				Z_TYPE(*z)
#define Z_TYPE_PP(z)			Z_TYPE_PP(z)

#define ZVAL_BOOL(z, b) {			\
		Z_TYPE_P(z) = IS_BOOL;		\
		Z_LVAL_P(z) = ((b) != 0);   \
	}

#define ZVAL_NULL(z) {				\
		Z_TYPE_P(z) = IS_NULL;		\
	}

#define ZVAL_LONG(z, l) {			\
		Z_TYPE_P(z) = IS_LONG;		\
		Z_LVAL_P(z) = l;			\
	}

#define ZVAL_DOUBLE(z, d) {			\
		Z_TYPE_P(z) = IS_DOUBLE;	\
		Z_DVAL_P(z) = d;			\
	}

#define ZVAL_STRING(z, s, duplicate) {	\
		const char *__s=(s);			\
		Z_STRLEN_P(z) = strlen(__s);	\
		Z_STRVAL_P(z) = (duplicate?strndup(__s, Z_STRLEN_P(z)):(char*)__s);\
		Z_TYPE_P(z) = IS_STRING;		\
	}

#define ZVAL_STRINGL(z, s, l, duplicate) {	\
		const char *__s=(s); int __l=l;		\
		Z_STRLEN_P(z) = __l;				\
		Z_STRVAL_P(z) = (duplicate?strndup(__s, __l):(char*)__s);\
		Z_TYPE_P(z) = IS_STRING;			\
	}

#define ZVAL_EMPTY_STRING(z) {		\
		Z_STRLEN_P(z) = 0;			\
		Z_STRVAL_P(z) = strndup("", sizeof("")-1);\
		Z_TYPE_P(z) = IS_STRING;	\
	}

#define ZVAL_FALSE(z)  					ZVAL_BOOL(z, 0)
#define ZVAL_TRUE(z)  					ZVAL_BOOL(z, 1)


//-----------------------HashTable相关定义----------------------
typedef void (*dtor_func_t)(void *);

typedef struct bucket{
	//原始索引号
	long h;
	//原始字符串长度
	int keyLength;
	//实际存储数据
	void *pData;
	struct bucket *pNext;
	struct bucket *pLast;
	//原始字符串
	char arKey[1];
}Bucket;

typedef struct _HashTable{
	//哈希表预分配尺寸
	int tableSize;
	//哈希表哈希掩码
	int tableMask;
	//哈希表当前元素数量
	int numOfElements;
	//哈希表存放的数组bucket
	Bucket **buckets;
	//元素析构函数
	dtor_func_t pDestructor;
	//-1未进行rehash，>0表示当前rehash到的索引
	int rehashidx;
}HashTable;

API int zend_rehash(HashTable *ht);
API int zend_hash_delete(HashTable *ht, zval *z, void **dest);
API int zend_hash_find(HashTable *ht, zval *z, void **dest);
API int zend_hash_set(HashTable *ht, zval *z, void *pData);
API HashTable* hash_init(HashTable *ht, int size, dtor_func_t destructor);

#endif